package com.y.report.service.api;

import cn.hutool.core.util.StrUtil;
import com.y.report.cons.ApiConstant;
import com.y.report.entity.api.ApiRequestInfo;
import com.y.report.entity.basic.YReportApi;
import com.y.report.entity.mapper.ApiReportInfo;
import com.y.report.exception.ApiExecption;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.condition.PatternsRequestCondition;
import org.springframework.web.servlet.mvc.condition.RequestMethodsRequestCondition;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import java.util.*;

@Service
public class ApiInterceptorService {

    private Logger log = LoggerFactory.getLogger(getClass());

    @Autowired
    private RequestMappingHandlerMapping mappingHandlerMapping;

    public boolean interceptor(ApiRequestInfo apiRequestInfo) {
        return StrUtil.isNotBlank(apiRequestInfo.getApiUrl()) && allProjectUrls().stream().noneMatch(x -> x.getOrDefault("url", "").equals(apiRequestInfo.getApiUrl()));
    }

    private List<Map<String, String>> allProjectUrls() {
        // 获取url与类和方法的对应信息
        Map<RequestMappingInfo, HandlerMethod> map = mappingHandlerMapping.getHandlerMethods();
        // 初始化map集合
        List<Map<String, String>> listMap = new ArrayList<>();
        for (Map.Entry<RequestMappingInfo, HandlerMethod> entry : map.entrySet()) {
            Map<String, String> initMap = new HashMap<>();
            RequestMappingInfo info = entry.getKey();
            // 请求类型
            RequestMethodsRequestCondition methodsCondition = info.getMethodsCondition();
            // 请求url
            PatternsRequestCondition pattern = info.getPatternsCondition();
            // 如果类型不为空则获取
            Set<RequestMethod> methods = methodsCondition.getMethods();
            if (!Objects.nonNull(pattern) && !CollectionUtils.isEmpty(methods)) {
                if (!CollectionUtils.isEmpty(pattern.getPatterns())) {
                    Set<String> patterns = pattern.getPatterns();
                    for (String url : patterns) {
                        initMap.put("url", url);
                        log.debug("方法url：{}", url);
                        initMap.put("name", url.replaceAll("/", "_").substring(1));
                        log.debug("方法名：{}", entry.getValue().getMethod().getName());
                    }
                    for (RequestMethod requestMethod : methods) {
                        initMap.put("type", requestMethod.toString());
                        log.debug("方法类型：{}", requestMethod.toString());
                    }
                }
                listMap.add(initMap);
            }
        }
        return listMap;
    }

    public boolean auth(ApiRequestInfo apiRequestInfo, ApiReportInfo apiReportInfo) {
        YReportApi yRrportApi = apiReportInfo.getYReportApi();
        String apiName = yRrportApi.getApiName();
        String apiCode = yRrportApi.getApiCode();
        String apiAuths = yRrportApi.getApiAuths();
        if (StrUtil.isNotBlank(apiAuths)) {
            boolean isAuth = Arrays.stream(apiAuths.split(","))
                    .filter(StrUtil::isNotBlank)
                    .map(String::trim)
                    .anyMatch(x -> x.equals(apiRequestInfo.getApiAuth()));

            if (!isAuth) {
                log.warn("api {} 授权失败!", apiRequestInfo.getApiUrl());
                apiReportInfo.getYReportApi().setRespStatus("403");
                throw new ApiExecption("api授权失败:" + apiRequestInfo.getApiUrl() + ", 请携带api授权信息：" + ApiConstant.API_HEADER_AUTH_KEY);
            }
            return isAuth;
        }
        return true;
    }
}
